﻿#region Copyright ©2008-2010, Technische Universitaet Muenchen
// ====================================================================================================
//
// Last Changed by       $Author: then $
// Last Changed Date     $LastChangedDate: 2009-06-15 08:45:45 +0200 (Mon, 15 Jun 2009) $
// Last Changed Revision $Rev: 194 $
//
// ====================================================================================================
#endregion

using System;
using System.Collections.Generic;
using System.Windows.Documents;

namespace Tum.CollabXT.Wizard
{
    /// <summary>
    /// Helper class for the Wizard.
    /// </summary>
    static class Helper
    {
        /// <summary>
        /// Tag type for use within FillInlineCollectionFromString.
        /// </summary>
        enum TagType
        {
            Normal,
            Italic,
        }

        /// <summary>
        /// Tag build structure for use within FillInlineCollectionFromString.
        /// </summary>
        struct TagSpan
        {
            public Span InnerSpan;
            public TagType Type;

            public TagSpan(TagType type)
            {
                InnerSpan = new Span();
                Type = type;
            }

            public Inline Finalize()
            {
                switch (Type)
                {
                    default:
                    case TagType.Normal:
                        return InnerSpan;
                    case TagType.Italic:
                        return new Italic(InnerSpan);
                }
            }
        }

        /// <summary>
        /// List of tags that can be used in inline collection strings.
        /// IMPORTANT: Do not change order.
        /// </summary>
        static string[] FillInlineTagStrings = { "<i>", "</i>" };

        /// <summary>
        /// Sets the content of an InlineCollection instance from an string.
        /// By now the only tags supported are linebreaks and italics.
        /// </summary>
        /// <param name="collection">InlineCollection to be filled.</param>
        /// <param name="inputString">InputProducts string that may contain tags.</param>
        internal static void FillInlineCollectionFromString(InlineCollection collection, string inputString)
        {
            Stack<TagSpan> spanChain = new Stack<TagSpan>();

            int curLinePos = 0;
            spanChain.Push(new TagSpan(TagType.Normal));

            string[] lines = inputString.Split(new string[] { "<br>" }, StringSplitOptions.None);
            foreach (string curLine in lines)
            {
                while (true)
                {
                    int foundTag;
                    int nextTagPos = curLine.IndexOfAnyString(FillInlineTagStrings, out foundTag, curLinePos);
                    if (nextTagPos > 0)
                    {
                        spanChain.Peek().InnerSpan.Inlines.Add(new Run(curLine.Substring(curLinePos, nextTagPos - curLinePos)));
                        switch (foundTag)
                        {
                            case 0:
                                spanChain.Push(new TagSpan(TagType.Italic));
                                break;
                            case 1:
                                var fin = spanChain.Pop().Finalize();
                                spanChain.Peek().InnerSpan.Inlines.Add(fin);
                                break;
                        }
                        curLinePos = nextTagPos + FillInlineTagStrings[foundTag].Length;
                        continue;
                    }

                    spanChain.Peek().InnerSpan.Inlines.Add(new Run(curLine.Substring(curLinePos)));
                    spanChain.Peek().InnerSpan.Inlines.Add(new LineBreak());
                    break;
                }
            }

            while (spanChain.Count > 1)
            {
                var fin = spanChain.Pop().Finalize();
                spanChain.Peek().InnerSpan.Inlines.Add(fin);
            }
            collection.Add(spanChain.Pop().Finalize());
        }

        /// <summary>
        /// Finds the first occurance of any of the passed strings within another string.
        /// </summary>
        /// <param name="stringsToBeFound">Array of strings to be searched for.</param>
        /// <param name="foundStringIndex">Output of the index of the string that was found.</param>
        /// <param name="startPos">The search starting position.</param>
        /// <returns>If found: Index of the first occurance, else -1.</returns>
        internal static int IndexOfAnyString(this string str, string[] stringsToBeFound, out int foundStringIndex, int startPos)
        {
            int minPos = -1;
            foundStringIndex = -1;
            for (int a = 0; a < stringsToBeFound.Length; a++)
            {
                int foundPos = str.IndexOf(stringsToBeFound[a], startPos, StringComparison.InvariantCulture);
                if (foundPos >= 0 && (minPos < 0 || foundPos < minPos))
                {
                    minPos = foundPos;
                    foundStringIndex = a;
                }
            }
            return minPos;
        }

        /// <summary>
        /// Creates the URI for an external page as they are used within plugins.
        /// </summary>
        /// <param name="assembly">Assembly the page is contained in.</param>
        /// <param name="pageName">Name of the page.</param>
        /// <returns>URI for the external page.</returns>
        internal static Uri GetExternalPageUri(string assembly, string pageName)
        {
            string tempAssemblyName = assembly.Substring(assembly.LastIndexOfAny(new char[] { '\\', '/' }) + 1);
            tempAssemblyName = tempAssemblyName.Substring(0, tempAssemblyName.LastIndexOf('.'));
            return new Uri("pack://application:,,,/" + tempAssemblyName + ";component/" + pageName);
        }

        /// <summary>
        /// Returns the file name from a path
        /// </summary>
        internal static string FileNameFromPath(string path)
        {
            return path.Substring(Math.Max(path.LastIndexOf('/'), path.LastIndexOf('\\')) + 1);
        }
    }
}
